package com.boarsoft.boar.batch.service;

import com.alibaba.fastjson.JSONObject;
import com.boarsoft.bean.ReplyInfo;
import com.boarsoft.boar.batch.biz.BatchExecutionBiz;
import com.boarsoft.boar.batch.biz.BatchReportBiz;
import com.boarsoft.boar.batch.entity.BatchExecution;
import com.boarsoft.boar.batch.entity.BatchRegist;
import com.boarsoft.boar.batch.entity.BatchReport;
import com.boarsoft.common.util.DateUtil;
import com.boarsoft.common.util.RandomUtil;
import com.boarsoft.common.util.StringUtil;
import com.boarsoft.hibernate.dao.SimpleDao;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description: 批量执行进度上报服务实现
 * @Author: 刘超
 * @Date: 2023-06-29 10:31
 * @update 上报接口调整 by tao.wangt57 2023-12-25
 */
public class BatchReportServiceImpl implements BatchReportService {

    private static final Logger log = LoggerFactory.getLogger(BatchReportServiceImpl.class);

    @Autowired
    private BatchReportBiz reportBiz;

    @Autowired
    private BatchExecutionBiz batchExecutionBiz;

    @Autowired
    protected SimpleDao simpleDao;

    @Autowired
    private com.boarsoft.boar.batch.mq.MsgProducer msgProducer;

    @Override
    public void sendMQ(String id, String batchId){
        Map<String, String> map = new HashMap<>();
        map.put("id", id);
        map.put("batchId", batchId);
        map.put("status", "COMPLETE");
        JSONObject jsonObject = (JSONObject) JSONObject.toJSON(map);
        try {
            msgProducer.send(jsonObject);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("when send batchId is {} occur Exception {}", e);
        }
    }

    /**
     * 直接上报
     * @param batchId  任务执行id
     * @param progress 执行进度 绝对进度：|5|，表示在原有进度的基础上增加5%；相对进度 +5， 表示在当前阶段中增加5%
     * @param phrase   执行阶段
     * @param addr     执行端IP地址
     * @return
     */
    @Override
    @Transactional
    public ReplyInfo<Object> report(String batchId, String progress, String phrase, String addr) {
        log.info(" receive report(batchId:{}, progress:{}, phrase:{}, addr:{}) timestamp:{}",
                batchId, progress, phrase, addr, System.currentTimeMillis());
        if (StringUtil.isEmpty(batchId)) {
            return ReplyInfo.error("batchId不允许为空");
        }
        if (StringUtil.isEmpty(progress)) {
            return ReplyInfo.error("progress不允许为空");
        }
        if (StringUtil.isEmpty(phrase)) {
            return ReplyInfo.error("phrase不允许为空");
        }
        if (StringUtil.isEmpty(addr)) {
            return ReplyInfo.error("addr不允许为空");
        }

        // 查询执行记录表
        BatchExecution batchExecution = batchExecutionBiz.getBybatchId(batchId);
        if (batchExecution == null) {
            return ReplyInfo.error("BatchExecution表中没找到对应的批量业务登记监息。");
        }
        List<BatchExecution> succeedExecution = reportBiz.saveAndUpdate(batchId, progress, phrase, addr);
        if(succeedExecution != null && succeedExecution.size() > 0){
            for(BatchExecution be:succeedExecution){
                sendMQ(be.getId(), be.getBatchId());
            }
        }
        return ReplyInfo.success("登记成功");
    }

    @Override
    @Transactional
    public ReplyInfo<Object> report(String batchId, String progress, String phrase, String addr, Object errMsg) {
        log.info(" receive report(batchId:{}, progress:{}, phrase:{}, addr:{}) timestamp:{}",
                batchId, progress, phrase, addr, System.currentTimeMillis());
        if (StringUtil.isEmpty(batchId)) {
            return ReplyInfo.error("batchId不允许为空");
        }
        if (StringUtil.isEmpty(progress)) {
            return ReplyInfo.error("progress不允许为空");
        }
        if (StringUtil.isEmpty(phrase)) {
            return ReplyInfo.error("phrase不允许为空");
        }
        if (StringUtil.isEmpty(addr)) {
            return ReplyInfo.error("addr不允许为空");
        }

        // 查询执行记录表
        BatchExecution batchExecution = batchExecutionBiz.getBybatchId(batchId);
        if (batchExecution == null) {
            return ReplyInfo.error("BatchExecution表中没找到对应的批量业务登记监息。");
        }
        List<BatchExecution> succeedExecution = reportBiz.saveAndUpdate(batchId, progress, phrase, addr, errMsg);
//        if(succeedExecution != null && succeedExecution.size() > 0){
//            for(BatchExecution be:succeedExecution){
//                sendMQ(batchExecution.getId(), batchExecution.getBatchId());
//            }
//        }
        return ReplyInfo.success("登记成功");
    }

    /**
     * 子任务执行前上报（子任务概要上报）
     * @param batchId      任务执行id
     * @param phrase       执行阶段
     * @param addr         执行端IP地址
     * @param childern     子任务数  （如总共分500页等）
     * @param childDataVol 子任务数据量 （如数据量为100000条等）
     * @param percent      子任务占比
     * @return
     */
    @Override
    @Transactional
    public ReplyInfo<Object> report(String batchId, String phrase, String addr, int childern, int childDataVol, int percent) {
        log.info(" receive report(batchId:{}, phrase:{}, addr:{}, childern:{}, childDataVol:{}, percent:{}) timestamp:{}",
                batchId, phrase, addr, childern, childDataVol, percent, System.currentTimeMillis());
        if (StringUtil.isEmpty(batchId)) {
            return ReplyInfo.error("batchId不允许为空");
        }
        if (StringUtil.isEmpty(phrase)) {
            return ReplyInfo.error("phrase不允许为空");
        }
        if (StringUtil.isEmpty(addr)) {
            return ReplyInfo.error("addr不允许为空");
        }
        String result = reportBiz.saveAndUpdatereport( batchId,  phrase,  addr,  childern,  childDataVol, percent);
//        if(BatchSts.COMPLETE.equals(result)){
//            sendMQ(null, batchId);
//        }
        return ReplyInfo.success("登记成功");
    }

    /**
     * 子任务上报
     * @param batchId  任务执行id
     * @param progress 执行进度，一般表述子任务的完成个数，此字段赋值为1即可
     * @param phrase   执行阶段
     * @param addr     执行端IP地址
     * @param index    执行序号，如分页编号
     * @return
     */
    @Override
    @Transactional
    public ReplyInfo<Object> report(String batchId, String progress, String phrase, String addr, String index) {
        log.info("收到 batchId:{},progress:{},phrase:{},addr:{},index:{} 的子任务上报 timesatmp:{}",
                batchId, progress, phrase, addr, index, System.currentTimeMillis());
        if (StringUtil.isEmpty(batchId)) {
            log.error("batchId不允许为空");
            return ReplyInfo.error("batchId不允许为空");
        }
        if (StringUtil.isEmpty(phrase)) {
            log.error("phrase不允许为空");
            return ReplyInfo.error("phrase不允许为空");
        }
        if (StringUtil.isEmpty(addr)) {
            log.error("addr不允许为空");
            return ReplyInfo.error("addr不允许为空");
        }
        if (StringUtil.isEmpty(index)) {
            log.error("index不允许为空");
            return ReplyInfo.error("index不允许为空");
        }
        reportBiz.saveReportAndExecution(batchId, progress, phrase, addr, index);
//        BatchExecution batchExecution = batchExecutionBiz.getBybatchId(batchId);
        //处理父节点状态
//        if(batchExecution.getStatus() == BatchExecution.STATUS_SUCCESS){
//            reportBiz.updateParentStsRecursion(batchExecution);
//        }
        return ReplyInfo.success("登记成功");
    }

    /**
     * 批量执行进度上报_详情明细上报。（根据上报记录数计算执行进度）
     *  be dependent on： ReplyInfo<Object> report(String batchId, String phrase, String addr, int childern, int childDataVol, int percent);
     *
     *
     * @param batchId   任务执行id
     * @param dealCount 当前页处理数据量，
     * @param phrase    执行阶段
     * @param addr      执行端IP地址
     * @param index     执行序号，如分页编号
     * @return
     */
    @Override
    @Transactional
    public ReplyInfo<Object> report(String batchId, int dealCount, String phrase, String addr, String index) {
        log.info("收到 batchId:{},dealCount:{},phrase:{},addr:{},index:{} 的子任务上报 timesatmp:{}",
                batchId, dealCount, phrase, addr, index, System.currentTimeMillis());
        if (StringUtil.isEmpty(batchId)) {
            log.error("batchId不允许为空");
            return ReplyInfo.error("batchId不允许为空");
        }
        if (StringUtil.isEmpty(phrase)) {
            log.error("phrase不允许为空");
            return ReplyInfo.error("phrase不允许为空");
        }
        if (StringUtil.isEmpty(addr)) {
            log.error("addr不允许为空");
            return ReplyInfo.error("addr不允许为空");
        }
        if (StringUtil.isEmpty(index)) {
            log.error("index不允许为空");
            return ReplyInfo.error("index不允许为空");
        }
        reportBiz.registSubProgress(batchId, dealCount, phrase, addr, index);
        BatchExecution batchExecution = batchExecutionBiz.getBybatchId(batchId);
        //处理父节点状态
//        if(batchExecution.getStatus() == BatchExecution.STATUS_SUCCESS){
//            reportBiz.updateParentStsRecursion(batchExecution);
//        }
        return ReplyInfo.success("登记成功");
    }

    /**
     * 异常上报
     * @param batchId 任务执行id
     * @param error   异常监息
     * @return
     */
    @Override
    @Transactional
    public ReplyInfo<Object> report(String batchId, String error) {
        if (StringUtil.isEmpty(batchId)) {
            return ReplyInfo.error("batchId不允许为空");
        }
        BatchExecution batchExecution = batchExecutionBiz.getBybatchId(batchId);

        BatchReport report = new BatchReport();
        report.setBatchId(batchId);
        report.setError((error != null && error.length() > 512) ? error.substring(0, 512) : error);
        report.setLastTime(DateUtil.yyyyMMddHHmmss());
        report.setNo(batchExecution.getNo());
        reportBiz.save(report);

        batchExecution.setError(error);
        batchExecution.setStatus(BatchExecution.STATUS_FAILED);
        batchExecutionBiz.update(batchExecution);
        return ReplyInfo.success("登记成功");
    }

    /**
     * 子任务异常上报
     * @param batchId 任务执行id
     * @param index   任务执行id
     * @param error   异常监息
     * @return
     */
    @Override
    @Transactional
    public ReplyInfo<Object> report(String batchId, String index, String error) {
        if (StringUtil.isEmpty(batchId)) {
            return ReplyInfo.error("batchId不允许为空");
        }
        if (StringUtil.isEmpty(index)) {
            return ReplyInfo.error("index不允许为空");
        }
        BatchExecution batchExecution = batchExecutionBiz.getBybatchId(batchId);

        BatchReport report = new BatchReport();
        report.setBatchId(batchId);
        report.setIndex(index);
        report.setError((error != null && error.length() > 512) ? error.substring(0, 512) : error);
        report.setLastTime(DateUtil.yyyyMMddHHmmss());
        report.setNo(batchExecution.getNo());
        reportBiz.save(report);

        batchExecution.setError(error);
        batchExecution.setStatus(BatchExecution.STATUS_FAILED);
        batchExecutionBiz.update(batchExecution);
        return ReplyInfo.success("登记成功");
    }

    /**
     * 根据当前批次号获取当前订单状态，以及生成子任务编号
     * @param batchId
     * @return
     */
    @Override
    @Transactional
    public ReplyInfo<Object> report(String batchId) {
        BatchExecution batchExecution = batchExecutionBiz.getBybatchId(batchId);
        //生成唯一id
        String uuid = RandomUtil.randomUUID();
        BatchExecution be = new BatchExecution();
        be.setBatchId(uuid);
        be.setParentId(batchExecution.getId());
        be.setPath(batchExecution.getPath() + "/" + uuid);
        batchExecutionBiz.save(be);
        //查询批次状态
        Map<String, String> result = new HashMap<>();
        result.put("status", String.valueOf(batchExecution.getStatus()));
        result.put("id", uuid);
        return ReplyInfo.success(result);
    }

    /**
     * 状态确认
     * @param batchId
     * @param cmd
     * @return
     */
    @Override
    @Transactional
    public ReplyInfo<Object> cmdReport(String batchId, short cmd) {
        BatchExecution batchExecution = batchExecutionBiz.getBybatchId(batchId);
        if (BatchExecution.STATUS_STOPPED == cmd) {
            log.info("收到 batchId:{}, cmd:{} 的 STATUS_STOPPED 指令确认。", batchId, cmd);
            batchExecution.setStatus(BatchExecution.STATUS_STOPPED);
        } else if (BatchExecution.STATUS_CANCELED == cmd) {
            log.info("收到 batchId:{}, cmd:{} 的 STATUS_CANCELED 指令确认。", batchId, cmd);
            batchExecution.setStatus(BatchExecution.STATUS_CANCELED);
        } else {
            log.error("收到 batchId:{} 未识别的指令确认 {}", batchId, cmd);
        }
        batchExecutionBiz.update(batchExecution);
        return ReplyInfo.SUCCESS;
    }

    /**
     * 开始上报，登记入参及flowId
     * @param batchId
     * @param addr
     * @param request
     * @param flowId
     * @return
     */
    @Override
    @Transactional
    public ReplyInfo<Object> startReport(String batchId, String addr, String request, String flowId) {
        BatchExecution batchExecution = batchExecutionBiz.getBybatchId(batchId);
        if(batchExecution == null){
            log.error("没有原始上报记录，无法进行 batchId:{} 的开始上报.", batchId);
            return ReplyInfo.error("没有原始上报记录，无法进行 batchId:"+batchId+" 的开始上报.");
        }
        batchExecution.setAddr(addr);
        batchExecution.setParams(new StringBuffer(request).append("|").append(flowId).toString());
        //batchExecution.setCode(flowId);
        batchExecutionBiz.update(batchExecution);
        return ReplyInfo.SUCCESS;
    }

    @Override
    public ReplyInfo<Object> executionRegist(BatchRegist executionRegist) {
        return ReplyInfo.error("方法已过期、请更新");
    }

    @Override
    public ReplyInfo<Object> executionReport(BatchReport executionReport) {
        return ReplyInfo.error("方法已过期、请更新");
    }
}
